package com.yoso.starter.boot.config;



import com.yoso.core.dto.ResponseResult;
import com.yoso.core.exception.BaseException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.core.annotation.Order;
import org.springframework.http.HttpStatus;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;
import java.util.Optional;

/**
 * <p>
 *   全局的的异常拦截器（拦截所有的控制器）（带有@RequestMapping注解的方法上都会拦截）
 * </p>
 *
 * @author shizejin
 * @version 1.0
 * @date 2023/2/27 11:03
 */
@Slf4j
@ControllerAdvice
@Order(600)
@ConditionalOnProperty(prefix = "exception-handler", name = "global", havingValue = "true", matchIfMissing = true)
public class GlobalExceptionHandler {

    @ExceptionHandler(value = Exception.class)
    @ResponseBody
    public ResponseResult<Object> defaultErrorHandler(HttpServletRequest req, Exception e) {
        log.error("################# ERROR START #####################");
        e.printStackTrace();
        log.error("URL：{}", req.getRequestURI());
        ResponseResult<Object> responseResult;
        if (e instanceof BindingResult) {
            responseResult = voValidErrorHandler(req, (BindingResult) e);
        } else if (e instanceof IllegalArgumentException) {
            IllegalArgumentException result = (IllegalArgumentException) e;
            responseResult = ResponseResult.error(HttpStatus.INTERNAL_SERVER_ERROR.value(), result.getMessage());
            log.error(String.format("ERROR CODE %s, ERROR INFO:", responseResult.getStatus()), e.getMessage(), e);
        } else if (e instanceof BaseException) {
            BaseException result = (BaseException) e;
            responseResult = ResponseResult.error(result.getStatus(), result.getMessage());
            log.error(String.format("ERROR CODE %s, ERROR INFO:", responseResult.getStatus()), e.getMessage(), e);
        } else {
            String message = "服务器异常，请联系管理员进行处理！";
            responseResult = ResponseResult.error(HttpStatus.INTERNAL_SERVER_ERROR.value(), message);
            log.error(String.format("ERROR CODE %s, ERROR INFO:", responseResult.getStatus()), e.getMessage(), e);
        }
        log.error("################# ERROR END #####################");
        return responseResult;
    }

    /**
     * 使用 @Validated 校验捕获的异常处理
     *
     * @param req           请求
     * @param bindingResult 校验结果
     * @return {@link ResponseResult }<{@link Object }>
     * @author shizejin
     * @date 2023/11/27 16:25
     */
    public ResponseResult<Object> voValidErrorHandler(HttpServletRequest req, BindingResult bindingResult) {
        ResponseResult<Object> responseResult = ResponseResult.error(HttpStatus.INTERNAL_SERVER_ERROR.value(),
                Optional.ofNullable(bindingResult.getFieldError()).map(FieldError::getDefaultMessage).orElse("未知的参数校验异常"));
        log.error("ERROR INFO：{}",
                bindingResult.getFieldError().getField() + " : " + bindingResult.getFieldError().getDefaultMessage());
        return responseResult;
    }


    /**
     * Unknown error handler response result
     *
     * @param req req
     * @param e   e
     * @return the response result
     */
    @ExceptionHandler(value = Throwable.class)
    @ResponseBody
    public ResponseResult<Object> unknownErrorHandler(HttpServletRequest req, Throwable e) {
        log.error("################# ERROR STAR #####################");
        log.error("URL：{}", req.getRequestURI());
        log.error("ERROR INFO: {}", e.getMessage(), e);
        String message = "服务器异常，请联系管理员进行处理！";
        log.error("################# ERROR END #####################");
        return ResponseResult.error(HttpStatus.INTERNAL_SERVER_ERROR.value(), message);
    }
}
